home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / bc31p1.zip / VNEWF.CPP < prev    next >
C/C++ Source or Header  |  1992-06-16  |  7KB  |  182 lines

  1. /*-----------------------------------------------------------------------*
  2.  * filename - vnewf.cpp
  3.  * C++ VECTOR_NEW
  4.  * Called internally by the compiler to allocate arrays of classes
  5.  *  having constructors
  6.  *-----------------------------------------------------------------------*/
  7.  
  8. /*
  9.  *      C/C++ Run Time Library - Version 5.0
  10.  *
  11.  *      Copyright (c) 1990, 1992 by Borland International
  12.  *      All Rights Reserved.
  13.  *
  14.  */
  15.  
  16.  
  17. #include <stdlib.h>
  18. #include <stdarg.h>
  19. #include <dos.h>
  20. #include <_vector.h>
  21.  
  22. void far * _vector_new_(void far *ptr,  // address of array, 0 means allocate
  23.         size_t size,                    // size of each object
  24.         unsigned long count,            // how many objects
  25.         unsigned mode,                  // actual type of constructor
  26.         ...
  27.         )
  28. /* This routine is used to initialize an array of class type.  If ptr is
  29.    NULL, it allocates the space for the array first.  Since the constructor
  30.    for the class may be of either memory model, and take an argument of any
  31.    memory model, we are forced to pass a mode parameter to tell us how to
  32.    cast it.  Since we must pass a near pointer for near functions and a
  33.    far call for far functions, we can't even know the argument type until
  34.    runtime, so we have to use varargs to get at it.
  35.  
  36.    If the constructor pointer is NULL no constructors are called.
  37.  
  38.    The interpretation of the mode parameter is:
  39.        far function    0x01     VFARCALL
  40.        pascal call     0x02     VPASCAL
  41.        far pointer     0x04     VFARPTR
  42.        deallocate      0x08     VDEALLOC
  43.        stored count    0x10     VSTORECNT
  44.        fastcall        0x20     VFASTCALL
  45.        huge vector     0x40     VHUGEVECT
  46.        fastthis        0x80     VFASTTHIS
  47.        this last       0x100    VTHISLAST
  48. */
  49. {
  50.     va_list ap;         // for access to parameters
  51.     constNNC np;        // near call version
  52.     constFNC fp;        // far call version
  53.     int construct = 1;  // flag whether to call constructors
  54.  
  55.     va_start(ap, mode);
  56.  
  57.     if (mode & VFARCALL)
  58.         {
  59.         fp = va_arg(ap, constFNC);
  60.         if (!fp)
  61.             construct = 0;
  62.         }
  63.     else
  64.         {
  65.         np = va_arg(ap, constNNC);
  66.         if (!np)
  67.             construct = 0;
  68.         }
  69.  
  70.     if (ptr == 0)               // should we allocate it?
  71.         {
  72.         unsigned Header;
  73.         unsigned Overhead = 0;
  74.         unsigned PadFromZero;
  75.  
  76.         if (mode & VSTORECNT)        // stored count
  77.             Overhead = sizeof(count);
  78.  
  79.         if (mode & VHUGEVECT)        // huge vector
  80.             {
  81.             Overhead += sizeof(Header);
  82.             ptr = operator new((unsigned long)count * size + Overhead + size);
  83.             if (!ptr)
  84.                 return 0;
  85.             PadFromZero = (unsigned) (65536L % size);
  86.             Header = FP_OFF(ptr);
  87.             while (PadFromZero < Overhead + Header)
  88.                 PadFromZero += size;
  89.  
  90.             (char far *)ptr += PadFromZero - Header - Overhead;
  91.             *(unsigned far *)ptr = Header;
  92.             ((unsigned far *)ptr)++;
  93.             }
  94.         else
  95.             {
  96.             // check that additional bytes don't make it go over 64K
  97.             unsigned long Length = size * count + Overhead;
  98.             if (Length > 0xFFFF)
  99.                 return 0;
  100.  
  101. #if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
  102.             // In large data model use default operator new
  103.             ptr = operator new((size_t)Length);
  104. #else       // In small data model need far pointer
  105.             ptr = operator new((unsigned long)Length);
  106. #endif
  107.             if (!ptr)
  108.                 return 0;
  109.             }
  110.  
  111.         // have ptr at either final location or count before
  112.  
  113.         if (mode & VSTORECNT)    // store count
  114.             {
  115.             *(unsigned long far *)ptr = count;
  116.             ((unsigned long far *)ptr)++;
  117.             }
  118.         }
  119.  
  120.     mode &= VCALLTYPE;      // strip out all flags except call type
  121.  
  122.     if (mode & VFASTTHIS)   // this-last has no effect with fast-this
  123.         mode &= ~(VTHISLAST);
  124.  
  125.     if (construct)
  126.         {
  127.         for (char huge *p = (char huge *) ptr; count-- > 0; p += size)
  128.             switch (mode)
  129.                 {
  130.                 case (VFARPTR):
  131.                     (*(constNFC) np)((void far *) p); break;
  132.                 case (VFARCALL | VFARPTR):
  133.                     (*(constFFC) fp)((void far *) p); break;
  134.                 case (VFARPTR | VPASCAL):
  135.                 case (VFARPTR | VPASCAL | VTHISLAST):
  136.                     (*(constNFP) np)((void far *) p); break;
  137.                 case (VFARCALL | VFARPTR | VPASCAL):
  138.                 case (VFARCALL | VFARPTR | VPASCAL | VTHISLAST):
  139.                     (*(constFFP) fp)((void far *) p); break;
  140.                 case (VFARPTR | VFASTCALL):
  141.                 case (VFARPTR | VFASTCALL | VTHISLAST):
  142.                     (*(constNFF) np)((void far *) p); break;
  143.                 case (VFARCALL | VFARPTR | VFASTCALL):
  144.                 case (VFARCALL | VFARPTR | VFASTCALL | VTHISLAST):
  145.                     (*(constFFF) fp)((void far *) p); break;
  146.                 case (VFARPTR | VFASTTHIS):
  147.                     LOAD_FAR_THIS(p);
  148.                     (*(constNFCT) np)();
  149.                     END_FAR_THIS();
  150.                     break;
  151.                 case (VFARCALL | VFARPTR | VFASTTHIS):
  152.                     LOAD_FAR_THIS(p);
  153.                     (*(constFFCT) fp)();
  154.                     END_FAR_THIS();
  155.                     break;
  156.                 case (VFARPTR | VPASCAL | VFASTTHIS):
  157.                     LOAD_FAR_THIS(p);
  158.                     (*(constNFPT) np)();
  159.                     END_FAR_THIS();
  160.                     break;
  161.                 case (VFARCALL | VFARPTR | VPASCAL | VFASTTHIS):
  162.                     LOAD_FAR_THIS(p);
  163.                     (*(constFFPT) fp)();
  164.                     END_FAR_THIS();
  165.                     break;
  166.                 case (VFARPTR | VFASTCALL | VFASTTHIS):
  167.                     LOAD_FAR_THIS(p);
  168.                     (*(constNFFT) np)();
  169.                     END_FAR_THIS();
  170.                     break;
  171.                 case (VFARCALL | VFARPTR | VFASTCALL | VFASTTHIS):
  172.                     LOAD_FAR_THIS(p);
  173.                     (*(constFFFT) fp)();
  174.                     END_FAR_THIS();
  175.                     break;
  176.                 default:
  177.                     abort(); break;
  178.                 }
  179.         }
  180.     return ptr;
  181. }
  182.